import tkinter as tk
from tkinter import ttk
import serial.tools.list_ports
import logging


class ControlPanel(ttk.Frame):
    """控制面板"""

    def __init__(self, parent, controller, config):
        super().__init__(parent)
        self.controller = controller
        self.config = config

        # 创建UI
        self.create_widgets()

        # 更新端口列表
        self.update_port_list()

    def create_widgets(self):
        """创建控件"""
        # 串口控制框架
        serial_frame = ttk.LabelFrame(self, text="串口控制")
        serial_frame.pack(fill=tk.X, padx=5, pady=5)

        # 串口选择
        port_frame = ttk.Frame(serial_frame)
        port_frame.pack(fill=tk.X, padx=5, pady=5)

        ttk.Label(port_frame, text="串口:").pack(side=tk.LEFT)
        self.port_var = tk.StringVar()
        self.port_combo = ttk.Combobox(port_frame, textvariable=self.port_var, width=15)
        self.port_combo.pack(side=tk.LEFT, padx=5)

        refresh_btn = ttk.Button(port_frame, text="刷新", command=self.update_port_list, width=8)
        refresh_btn.pack(side=tk.LEFT)

        # 设备地址
        addr_frame = ttk.Frame(serial_frame)
        addr_frame.pack(fill=tk.X, padx=5, pady=5)

        ttk.Label(addr_frame, text="设备地址:").pack(side=tk.LEFT)
        self.addr_var = tk.IntVar(value=self.config.get_modbus_config().get("device_address", 1))
        addr_spin = ttk.Spinbox(addr_frame, from_=1, to=247, textvariable=self.addr_var, width=8)
        addr_spin.pack(side=tk.LEFT, padx=5)
        addr_spin.bind("<<Increment>>", self.update_device_address)
        addr_spin.bind("<<Decrement>>", self.update_device_address)

        # 连接按钮
        btn_frame = ttk.Frame(serial_frame)
        btn_frame.pack(fill=tk.X, padx=5, pady=10)

        self.connect_btn = ttk.Button(btn_frame, text="连接", command=self.toggle_connection)
        self.connect_btn.pack(side=tk.LEFT, expand=True, padx=5)

        self.poll_btn = ttk.Button(btn_frame, text="开始轮询", command=self.toggle_polling, state=tk.DISABLED)
        self.poll_btn.pack(side=tk.LEFT, expand=True, padx=5)

        # 状态指示器
        status_frame = ttk.Frame(serial_frame)
        status_frame.pack(fill=tk.X, padx=5, pady=5)

        self.status_label = ttk.Label(status_frame, text="状态: 未连接", foreground="red")
        self.status_label.pack(side=tk.LEFT, anchor=tk.W)

        self.comm_status_var = tk.StringVar(value="通信: 未活动")
        comm_status_label = ttk.Label(status_frame, textvariable=self.comm_status_var, foreground="gray")
        comm_status_label.pack(side=tk.RIGHT, anchor=tk.E)

        # 寄存器操作框架
        reg_frame = ttk.LabelFrame(self, text="寄存器操作")
        reg_frame.pack(fill=tk.X, padx=5, pady=5)

        read_frame = ttk.Frame(reg_frame)
        read_frame.pack(fill=tk.X, padx=5, pady=2)

        ttk.Label(read_frame, text="地址:").pack(side=tk.LEFT)
        self.read_addr_var = tk.StringVar()
        read_addr_entry = ttk.Entry(read_frame, textvariable=self.read_addr_var, width=8)
        read_addr_entry.pack(side=tk.LEFT, padx=5)

        ttk.Label(read_frame, text="数量:").pack(side=tk.LEFT)
        self.read_count_var = tk.StringVar(value="1")
        read_count_entry = ttk.Entry(read_frame, textvariable=self.read_count_var, width=5)
        read_count_entry.pack(side=tk.LEFT, padx=5)

        read_btn = ttk.Button(read_frame, text="读取", command=self.read_registers)
        read_btn.pack(side=tk.LEFT, padx=5)

        write_frame = ttk.Frame(reg_frame)
        write_frame.pack(fill=tk.X, padx=5, pady=2)

        ttk.Label(write_frame, text="地址:").pack(side=tk.LEFT)
        self.write_addr_var = tk.StringVar()
        write_addr_entry = ttk.Entry(write_frame, textvariable=self.write_addr_var, width=8)
        write_addr_entry.pack(side=tk.LEFT, padx=5)

        ttk.Label(write_frame, text="值:").pack(side=tk.LEFT)
        self.write_value_var = tk.StringVar()
        write_value_entry = ttk.Entry(write_frame, textvariable=self.write_value_var, width=8)
        write_value_entry.pack(side=tk.LEFT, padx=5)

        write_btn = ttk.Button(write_frame, text="写入", command=self.write_register)
        write_btn.pack(side=tk.LEFT, padx=5)

    def update_port_list(self):
        """更新可用串口列表"""
        ports = self.controller.get_available_ports()
        self.port_combo['values'] = ports
        if ports:
            self.port_var.set(ports[0])

    def update_device_address(self, event=None):
        """更新设备地址"""
        try:
            self.controller.set_device_address(self.addr_var.get())
            logging.info(f"设备地址更新为: {self.addr_var.get()}")
        except tk.TclError:
            pass

    def toggle_connection(self):
        """切换连接状态"""
        if self.controller.is_connected():
            self.controller.disconnect()
            self.connect_btn.config(text="连接")
            self.poll_btn.config(text="开始轮询", state=tk.DISABLED)
            self.status_label.config(text="状态: 未连接", foreground="red")
            self.comm_status_var.set("通信: 未活动")
        else:
            port = self.port_var.get()
            if self.controller.connect(port):
                self.connect_btn.config(text="断开")
                self.poll_btn.config(state=tk.NORMAL)
                self.status_label.config(text="状态: 已连接", foreground="green")

    def toggle_polling(self):
        """切换轮询状态"""
        if self.controller.is_polling():
            self.controller.stop_polling()
            self.poll_btn.config(text="开始轮询")
            self.comm_status_var.set("通信: 已停止")
        else:
            self.controller.start_polling()
            self.poll_btn.config(text="停止轮询")
            self.comm_status_var.set("通信: 轮询中")

    def read_registers(self):
        """读取寄存器"""
        try:
            start_addr = self.config.data_utils.hex_to_int(self.read_addr_var.get())
            count = int(self.read_count_var.get())
            self.controller.read_registers(start_addr, count)
        except ValueError:
            logging.error("无效的地址或数量")

    def write_register(self):
        """写入寄存器"""
        try:
            address = self.config.data_utils.hex_to_int(self.write_addr_var.get())
            value = int(self.write_value_var.get())
            self.controller.write_register(address, value)
        except ValueError:
            logging.error("无效的地址或值")

    def update_status(self, connected, polling):
        """更新状态显示"""
        if connected:
            self.status_label.config(text="状态: 已连接", foreground="green")
            self.connect_btn.config(text="断开")
            self.poll_btn.config(state=tk.NORMAL)

            if polling:
                self.poll_btn.config(text="停止轮询")
                self.comm_status_var.set("通信: 轮询中")
            else:
                self.poll_btn.config(text="开始轮询")
                self.comm_status_var.set("通信: 已连接")
        else:
            self.status_label.config(text="状态: 未连接", foreground="red")
            self.connect_btn.config(text="连接")
            self.poll_btn.config(text="开始轮询", state=tk.DISABLED)
            self.comm_status_var.set("通信: 未活动")
